# This file encapsulation functions offen used

import os, re
from contextlib import nested
import smtplib
from email.mime.text import MIMEText
from models import Machine, IPSRepo
import const, conf


#
# connect ilom/elom console by ssh from terminal
#   ticssh sp_hostname 
# connect alom console by telnet from terminal
#   tactel sp_hostname
# connect ldom console by telnet from terminal
#   tlctel sp_hostname port
# connect sp by ssh from terminal
#   tspssh sp_hostname
# connect os by ssh from terminal
#   tosssh os_hostname user
def get_jnlpurl(args, domain):
    url = ''
    if not args:
        return url

    anum = len(args)
    cmd_type = args[0]
    if cmd_type == 'ticssh' or \
       cmd_type == 'tactel' or \
       cmd_type == 'tspssh':
        if anum >= 2:
            url = "%s?type=%s&a1=%s.%s" % (conf.JNLP_URL, args[0], args[1], domain)
    elif cmd_type == 'tlctel' or \
         cmd_type == 'tosssh':
        if anum >= 3:
            url = "%s?type=%s&a1=%s.%s&a2=%s" % (conf.JNLP_URL, args[0], args[1], domain, args[2])
        
    return url

def get_cslurl(sp_info, domain):
    if sp_info:
        return get_jnlpurl(sp_info.split(conf.FORM_VALUE_FS), domain)
    else:
        return ''

def get_osurl(hostname, domain):
    return get_jnlpurl(('tosssh', hostname, conf.CTE_USER), domain)


def get_vncurl(hostname, domain):
    return "http://%s.%s:%d" % (hostname, domain, conf.VNC_PORT)


def sendemail(subject, body, to, cc=[], frm=conf.DAEMON_USER_EMAIL):
    msg = MIMEText(body, "plain")
    msg["Subject"] = subject
    msg["From"] = frm
    msg["To"] = ",".join(to)
    if cc:
        for addr in cc:
            if addr in to:
                cc.remove(addr)

    if cc:
        msg["Cc"] = ",".join(cc)
        to.extend(cc)

    server = smtplib.SMTP("localhost")
    server.sendmail(frm, to, msg.as_string())
    server.quit()

#ip = request.META["REMOTE_ADDR"]
def get_site(ip):
    # default site is bj_zpk
    site = "bj_zpk"
    with open(conf.ETC_IP2SITE, "r") as f:
        for l in f:
            if re.search(r'^\s#|^\s*$', l):
                continue
     
            cols = l.split()
            if re.match(r"%s" % cols[0], ip):
                site = cols[1]
                break
                
    return site

def get_bldlst(site_id, os_rel):
    hit_site_flag = False
    blst = ()
    # note: site_id is a string type
    with open(conf.BUILD_LIST, "r") as f:
        for l in f:
            if re.search(r'^\s*#|^\s*$', l):
                continue
     
            m = re.search(r'\[\s*(\d+):', l) 
            if m:
                if hit_site_flag:
                    # the target site's section is over and
                    # nothing matched with the target os release
                    break
                elif m.group(1) == site_id:
                    # this is the target site
                    hit_site_flag = True
                    continue
            elif hit_site_flag:
                if re.search(r"^\s*%s:" % os_rel, l):
                    # reverse build list to put latest build on top
                    tmplst = l.split(':')[3].split()
                    tmplst.reverse()
                    blst = tuple(tmplst)
                    break
                
    return blst


def gen_scprofile(machine, repo, os_rel):
    """
    Looking for the template in the order:
      template.site.os_rel 
      template.site
    """

    tmpl = "%s.%s" % (conf.SCPROFILE_TEMPLATE, machine.site.name)
    os_tmpl = "%s.%s" % (tmpl, os_rel)
    if os.path.isfile(os_tmpl):
        tmpl = os_tmpl
    elif not os.path.isfile(tmpl):
        raise IOError("SC profile template does not exist: %s" % tmpl)
   
    scp = "%s/%s.xml" % \
          (os.path.dirname(conf.SCPROFILE_TEMPLATE), 
           machine.hostname)

    mtype_int = machine.mgroup.machine_type
    with nested(open(tmpl, "r"), open(scp, "w")) as (sf, df):
        for l in sf:
            # note that l contains "\n"
            if l.find("<!-- PUT ADDITIONAL SETTING HERE -->") != -1:
                if mtype_int in (const.MACHINE_TYPE_AUTOTEST, \
                                 const.MACHINE_TYPE_MANTEST):

                    mtype = machine.mgroup.get_machine_type_display().lower()
                    hwm = machine.hwmode.name
                    itype = machine.mgroup.get_intg_type_display().lower()
                    btype = ""
                    if machine.mgroup.dtbld_type == const.DTBLD_TYPE_DEFAULT:
                        btype = os_rel
                    else:
                        btype = machine.mgroup.get_dtbld_type_display().lower()

                    trs = '\n'
                    for tr in machine.mgroup.testrun.all():
                        trs += "            <value_node value='%s'/>\n" % tr.name
 
                    df.write(
"""
  <!-- PUT ADDITIONAL SETTING HERE -->

  <!-- set cte-deploy service -->
  <service version="1" type="service" name="application/desktop-test/cte-deploy">
    <instance enabled="true" name="default"/>
    <property_group name='args' type='application'>
        <!-- machine_use: (autotest|mantest) -->
        <propval name='machine_type' type='astring' value='%s' />
        <propval name='hw_model' type='astring' value='%s' />
        <!-- integration_type: (pre|post) -->
        <propval name='integration_type' type='astring' value='%s'/>
        <propval name='os_release' type='astring' value='%s' />
        <propval name='osbld_no' type='astring' value='' />
        <!-- dtbld_type: (stable|devel) -->
        <propval name='dtbld_type' type='astring' value='%s' />
        <propval name='dtbld_no' type='astring' value='' />
        <propval name='bld_no' type='astring' value='' />
        <!-- testruns: (a11y|firefox|ipsgui|xorg) -->
        <property name='testruns' type='astring'>
          <astring_list>%s
          </astring_list>
        </property> 
        <propval name='wox_ips_repo' type='astring' value='%s' />
        <propval name='os_ips_repo' type='astring' value='%s' />
        <propval name='cte_user' type='astring' value='%s' />
    </property_group>
  </service>

  <!-- set wsa service -->
  <service version="1" type="service" name="application/desktop-test/woxsagent">
    <instance enabled="true" name="default"/>
    <property_group name='args' type='application'>
        <propval name='wsa_monitor_url' type='astring' value='%s' />
        <!-- message field separator -->
        <propval name='wsa_mfs' type='astring' value='%s' />
        <propval name='wsa_pipe' type='astring' value='%s' />
        <propval name='wsa_twmax' type='integer' value='%s' />
        <propval name='wsa_term_token' type='astring' value='%s' />
    </property_group>
  </service>

""" % (mtype,
       hwm,
       itype,
       os_rel,
       btype,
       trs,
       repo.wox_ips_repo,
       repo.os_ips_repo,
       conf.CTE_USER,
       conf.WSA_MONITOR_URL,
       conf.WSA_MFS,
       conf.WSA_PIPE,
       conf.WSA_TWMAX,
       conf.WSA_TERM_TOKEN))
                #elif mtype_int == other value:
                else:
                    pass
            else:
                df.write(l)
            # end of if l.find

    return "%s%s" % (conf.AI_NFS_PREFIX, scp)


#generate ai mainfest
def gen_aimanifest(machine, repo, os_rel, bld_no):
    """
    Looking for the template in the order:
      template
      template.os_rel
    """

    # FIXME: move these data in database
    OS_BRANCH_NO_PRE = { 's11':   '@0.5.11-0.175.0.0.0.',
                         's11u1': '@0.5.11-0.175.1.0.0.',
                         's11u2': '@0.5.11-0.175.2.0.0.',
                         's11u3': '@0.5.11-0.175.3.0.0.',
                         's11u4': '@0.5.11-0.175.4.0.0.',
                         's11u5': '@0.5.11-0.175.5.0.0.',
                         's11u6': '@0.5.11-0.175.6.0.0.',
                         's11u7': '@0.5.11-0.175.7.0.0.',
                         's11u8': '@0.5.11-0.175.8.0.0.',
                         's11u9': '@0.5.11-0.175.9.0.0.',
                         's12':   '@5.12-5.12.0.0.0.', }
    if (os_rel in OS_BRANCH_NO_PRE):
        os_branch_no = "%s%s" % (OS_BRANCH_NO_PRE[os_rel], re.sub('[a-d]', '', bld_no))
    else:
        os_branch_no = ""

    tmpl = conf.AIMANIFEST_TEMPLATE
    os_tmpl = "%s.%s" % (tmpl, os_rel)
    if os.path.isfile(os_tmpl):
        tmpl = os_tmpl
    elif not os.path.isfile(tmpl):
        raise IOError("AI manifest template does not exist: %s" % tmpl)

    aim = "%s/%s.xml" % \
          (os.path.dirname(conf.AIMANIFEST_TEMPLATE), 
           machine.hostname)
    
    # group pkg could be different per other machine types in the future
    os_group_pkg = "pkg:/group/system/solaris-desktop"
    mtype_int = machine.mgroup.machine_type
    with nested(open(tmpl, "r"), open(aim, "w")) as (sf, df):
        for l in sf:
            # note that l contains "\n"
            # substitute variables 
            if l.find("%%BE_NAME%%") != -1:
                df.write(l.replace("%%BE_NAME%%", "%s_%s" % (os_rel, bld_no)))
            elif l.find("%%OS_IPS_REPO%%") != -1:
                df.write(l.replace("%%OS_IPS_REPO%%", repo.os_ips_repo))
            elif l.find("%%OS_BRANCH_NO%%") != -1:
                df.write(l.replace("%%OS_BRANCH_NO%%", os_branch_no))
            elif l.find("%%OS_GROUP_PKG%%") != -1:
                df.write(l.replace("%%OS_GROUP_PKG%%", os_group_pkg))
            elif l.find("<!-- PUT ADDITIONAL SETTING HERE -->") != -1:
                # add additional settings for test machines
                if mtype_int == const.MACHINE_TYPE_AUTOTEST or \
                   mtype_int == const.MACHINE_TYPE_MANTEST:
                    df.write(
"""
    <!-- PUT ADDITIONAL SETTING HERE -->

    <!-- install cte-deploy service -->
    <software type="IPS">
      <source>
        <publisher name="wox">
          <origin name="%s" />
        </publisher>
      </source>
      <software_data action="install">
        <name>pkg:/desktop/gui-test/cte-deploy</name>
      </software_data>
    </software>
""" % repo.wox_ips_repo)

            else:
                # handle the specific cases here
                if machine.hostname == 'jdstest26' and \
                   re.search(r'(?i)<disk_keyword\s*key=.boot_disk', l):
                    df.write('        <disk_name name="c8t0d0" name_type="ctd"/>\n')
                elif machine.hostname == 'sunray-verm-02' and \
                   re.search(r'(?i)<disk_keyword\s*key=.boot_disk', l):
                    df.write('%s\n          <partition action="use_existing_solaris2" part_type="191"/>\n' % l)
                else:
                    df.write(l)

    return "%s%s" % (conf.AI_NFS_PREFIX, aim)


def uniqify_list(seq):
    # not order preserving
    set = {}
    map(set.__setitem__, seq, [])
    return set.keys()

import logging 
def debug(msg): 
    logging.info("\n++++++++ DEBUG ++++++++\n%s\n+++++++++++++++++++++++\n" % msg) 

